import java.util.Iterator;
import java.util.LinkedList;

import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleWeightedGraph;

public class OverlapsSolverRWCAllowSingleOL implements OverlapsSolver {
	private ClusterConnectivityInspector _connectivityInspector;
	private int _minClusterSize;
	
	public OverlapsSolverRWCAllowSingleOL() {
		this(1, null);
	}
	
	public OverlapsSolverRWCAllowSingleOL(int minClusterSize, SimpleWeightedGraph<String, DefaultWeightedEdge> graph) {
		_connectivityInspector = new ClusterConnectivityInspector(graph);
		_minClusterSize = minClusterSize;
	}
	
	public void setGraph(SimpleWeightedGraph<String, DefaultWeightedEdge> g) {
		_connectivityInspector = new ClusterConnectivityInspector(g);		
	}
	
	public void setMinClusterSize(int x) {
		_minClusterSize = x;
	}
	
	public int getMinClusterSize() {
		return _minClusterSize;
	}
	
	/**
	 * Resolves overlaps by removing clusters that have overlaps and are considered lesser.
	 * Tries to first remove the overlapping genes discards clusters that become disconnected
	 * After the removal of these genes.
	 * The clusters list is assumed to be ordered s.t. the 'strongest' cluster is at the head 
	 * and the weaker is at the tail.
	 */
	public void solve(LinkedList<Cluster> clusters) {
		if (_connectivityInspector == null)
			return;
		
		int totalDisconnected = 0; // TEMP TODO REMOVE
		
		Iterator<Cluster> citer = clusters.descendingIterator();
		while (citer.hasNext()) {
			Cluster cluster = citer.next();
			Iterator<Gene> giter = cluster.iterator();
			while (giter.hasNext()) {
				Gene g = giter.next();
				if (g.clustersCount() > 1) {
					 // Workaround concurrent removal problem.
					giter.remove();
					g.removeCluster(cluster);
					 // End Workaround concurrent removal problem.
				}
			}

			// If cluster was left without genes - discard it.
			if (cluster.size() < _minClusterSize) {
				citer.remove();
				continue;
			}
			
			// Check if the remaining genes are connected.
			 
					
			if (!_connectivityInspector.isClusterConnected(cluster)) {
				cluster.clear();
				citer.remove();
			}
		} // end while (citer)
		
		// TEMP TODO sanity check
/*
		for (Cluster c: clusters) {
			Set<String> vertices = c.memberNames();
			UndirectedWeightedSubgraph<String, DefaultWeightedEdge> subgraph = 
				new UndirectedWeightedSubgraph<String, DefaultWeightedEdge>(_graph, vertices, null);
			
			ConnectivityInspector<String, DefaultWeightedEdge> connectivityInspector = 
				new ConnectivityInspector<String, DefaultWeightedEdge>(subgraph); 
			
			if (!connectivityInspector.isGraphConnected()) {
				++totalDisconnected;
			}
		}
	*/	
	}

}
